{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "7FV_m2u2Hny8"
   },
   "source": [
    "##### Copyright 2022 The Cirq Developers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "cellView": "form",
    "id": "2XSh1-J7HrcU"
   },
   "outputs": [],
   "source": [
    "# @title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "# https://www.apache.org/licenses/LICENSE-2.0\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Me7G0WVTHwHg"
   },
   "source": [
    "# Cirq basics"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "aAFfDwu7IFyx"
   },
   "source": [
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://quantumai.google/cirq/start/basics\"><img src=\"https://quantumai.google/site-assets/images/buttons/quantumai_logo_1x.png\" />View on QuantumAI</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/quantumlib/Cirq/blob/main/docs/start/basics.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/colab_logo_1x.png\" />Run in Google Colab</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/quantumlib/Cirq/blob/main/docs/start/basics.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/github_logo_1x.png\" />View source on GitHub</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a href=\"https://storage.googleapis.com/tensorflow_docs/Cirq/docs/start/basics.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/download_icon_1x.png\" />Download notebook</a>\n",
    "  </td>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "67gUU740MSXd"
   },
   "source": [
    "This tutorial will teach the basics of how to use Cirq. It will walk through how to use qubits, gates, and operations to create and simulate your first quantum circuit using Cirq.  It will briefly introduce devices, unitary matrices, decompositions, and transformers as well.\n",
    "\n",
    "This tutorial isn’t a quantum computing 101 tutorial: it assumes familiarity of quantum computing at about the level of the textbook “Quantum Computation and Quantum Information” by Nielsen and Chuang.\n",
    "\n",
    "For more in-depth examples of quantum algorithms and experiments, see [Experiments](../experiments)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "1dOjJlgrNUuz"
   },
   "source": [
    "To begin, please follow the instructions for [installing Cirq](./install.md)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "bd9529db1c0b"
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    import cirq\n",
    "except ImportError:\n",
    "    print(\"installing cirq...\")\n",
    "    !pip install --quiet cirq\n",
    "    print(\"installed cirq.\")\n",
    "    import cirq\n",
    "\n",
    "import cirq_google"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "xr-MMoXgNsUQ"
   },
   "source": [
    "## Qubits\n",
    "\n",
    "The first part of creating a quantum circuit is to define a set of qubits (also known as a quantum register) to act on.\n",
    "\n",
    "Cirq has three main ways of defining qubits:\n",
    "\n",
    "*   `cirq.NamedQubit`: used to label qubits by an abstract name.\n",
    "*   `cirq.LineQubit`: qubits labelled by number in a linear array.\n",
    "*   `cirq.GridQubit`: qubits labelled by two numbers in a rectangular lattice.\n",
    "\n",
    "Here are some examples of defining each type of qubit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "PsgSo-H0Os8X"
   },
   "outputs": [],
   "source": [
    "# Using named qubits can be useful for abstract algorithms\n",
    "# as well as algorithms not yet mapped onto hardware.\n",
    "q0 = cirq.NamedQubit('source')\n",
    "q1 = cirq.NamedQubit('target')\n",
    "\n",
    "# Line qubits can be created individually\n",
    "q3 = cirq.LineQubit(3)\n",
    "\n",
    "# Or created in a range\n",
    "# This will create LineQubit(0), LineQubit(1), LineQubit(2)\n",
    "q0, q1, q2 = cirq.LineQubit.range(3)\n",
    "\n",
    "# Grid Qubits can also be referenced individually\n",
    "q4_5 = cirq.GridQubit(4, 5)\n",
    "\n",
    "# Or created in bulk in a square\n",
    "# This will create 16 qubits from (0,0) to (3,3)\n",
    "qubits = cirq.GridQubit.square(4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "4zE6AutyQhQ6"
   },
   "source": [
    "There are also pre-packaged sets of qubits called [Devices](../hardware/devices.ipynb).  These are qubits along with a set of rules for how they can be used.  A `cirq.Device` can be used to ensure that two-qubit gates are only applied to qubits that are adjacent in the hardware, and other constraints.  The following example will use the `cirq_google.Sycamore` device that comes with cirq.  It is a diamond-shaped grid with 54 qubits that mimics early hardware released by Google."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "B0Dwgu-lQLpq"
   },
   "outputs": [],
   "source": [
    "print(cirq_google.Sycamore)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "j1QTjyxLSe5c"
   },
   "source": [
    "## Gates and operations\n",
    "\n",
    "The next step is to use the qubits to create operations that can be used in the circuit.  Cirq has two concepts that are important to understand here:\n",
    "\n",
    "*   A `Gate` is an effect that can be applied to a set of qubits.  \n",
    "*   An `Operation` is a gate applied to a set of qubits.\n",
    "\n",
    "For instance, `cirq.H` is the quantum [Hadamard](https://en.wikipedia.org/wiki/Quantum_logic_gate#Hadamard_(H)_gate) and is a `Gate` object.  `cirq.H(cirq.LineQubit(1))` is an `Operation` object and is the Hadamard gate applied to a specific qubit (line qubit number 1).\n",
    "\n",
    "Many textbook gates are included within cirq.  `cirq.X`, `cirq.Y`, and `cirq.Z` refer to the single-qubit Pauli gates.  `cirq.CZ`, `cirq.CNOT`, `cirq.SWAP` are a few of the common two-qubit gates.  `cirq.measure` is a macro to apply a `MeasurementGate` to a set of qubits.  You can find more, as well as instructions on how to create your own custom gates, on the [Gates documentation](../build/gates.ipynb) page.\n",
    "\n",
    "Here are some examples of operations that can be performed on gates and operations:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "wDW-yU-fesDl"
   },
   "outputs": [],
   "source": [
    "# Example gates\n",
    "cnot_gate = cirq.CNOT\n",
    "pauli_z = cirq.Z\n",
    "\n",
    "# Use exponentiation to get square root gates.\n",
    "sqrt_x_gate = cirq.X**0.5\n",
    "\n",
    "# Some gates can also take parameters\n",
    "sqrt_sqrt_y = cirq.YPowGate(exponent=0.25)\n",
    "\n",
    "# Create two qubits at once, in a line.\n",
    "q0, q1 = cirq.LineQubit.range(2)\n",
    "\n",
    "# Example operations\n",
    "z_op = cirq.Z(q0)\n",
    "not_op = cirq.CNOT(q0, q1)\n",
    "sqrt_iswap_op = cirq.SQRT_ISWAP(q0, q1)\n",
    "\n",
    "# You can also use the gates you specified earlier.\n",
    "cnot_op = cnot_gate(q0, q1)\n",
    "pauli_z_op = pauli_z(q0)\n",
    "sqrt_x_op = sqrt_x_gate(q0)\n",
    "sqrt_sqrt_y_op = sqrt_sqrt_y(q0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "BnBGLMVvWVkz"
   },
   "source": [
    "## Circuits and moments\n",
    "\n",
    "You are now ready to construct a quantum circuit.  A `Circuit` is a collection of `Moment`s. A `Moment` is a collection of `Operation`s that all act during the same abstract time slice.  Each `Operation` must be applied to a disjoint set of qubits compared to each of the other `Operation`s in the `Moment`.  A `Moment` can be thought of as a vertical slice of a quantum circuit diagram.\n",
    "\n",
    "Circuits can be constructed in several different ways.  By default, Cirq will attempt to slide your operation into the earliest possible `Moment` when you insert it. You can use the append function in two ways: \n",
    "\n",
    "By appending each operation one-by-one: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "HEuqEZcXkz3Q"
   },
   "outputs": [],
   "source": [
    "circuit = cirq.Circuit()\n",
    "qubits = cirq.LineQubit.range(3)\n",
    "circuit.append(cirq.H(qubits[0]))\n",
    "circuit.append(cirq.H(qubits[1]))\n",
    "circuit.append(cirq.H(qubits[2]))\n",
    "print(circuit)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ccd445492b19"
   },
   "source": [
    "Or by appending some iterable of operations. A preconstructed list works:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "HEuqEZcXkz3Q"
   },
   "outputs": [],
   "source": [
    "circuit = cirq.Circuit()\n",
    "ops = [cirq.H(q) for q in cirq.LineQubit.range(3)]\n",
    "circuit.append(ops)\n",
    "print(circuit)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "a0a5de4d8f01"
   },
   "source": [
    "A generator that yields operations also works. This syntax will be used often in documentation, and works both with the `cirq.Circuit()` initializer and the `cirq.Circuit.append()` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "HEuqEZcXkz3Q"
   },
   "outputs": [],
   "source": [
    "# Append with generator\n",
    "circuit = cirq.Circuit()\n",
    "circuit.append(cirq.H(q) for q in cirq.LineQubit.range(3))\n",
    "print(circuit)\n",
    "# Initializer with generator\n",
    "print(cirq.Circuit(cirq.H(q) for q in cirq.LineQubit.range(3)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "a6bd4d3152d5"
   },
   "source": [
    "Note that all of the Hadamard gates are pushed as far left as possible, and put into the same Moment since none overlap.\n",
    "\n",
    "If your operations are applied to the same qubits, they will be put in sequential, insertion-ordered moments. In the following example, the two-qubit gates overlap, and are placed in consecutive moments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "Lbez4guQl31P"
   },
   "outputs": [],
   "source": [
    "print(cirq.Circuit(cirq.SWAP(q, q + 1) for q in cirq.LineQubit.range(3)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "3FC9bdlXmShh"
   },
   "source": [
    "Sometimes, you may not want Cirq to automatically shift operations all the way to the left.  To construct a circuit without doing this, you can create the circuit moment-by-moment or use a different `InsertStrategy`, explained more in the [Circuit documentation](../build/circuits.ipynb)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "4AEahodTnYiI"
   },
   "outputs": [],
   "source": [
    "# Creates each gate in a separate moment by passing an iterable of Moments instead of Operations.\n",
    "print(cirq.Circuit(cirq.Moment([cirq.H(q)]) for q in cirq.LineQubit.range(3)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "j406AKYsobpq"
   },
   "source": [
    "### Circuits and devices\n",
    "\n",
    "One important consideration when using real quantum devices is that there are often constraints on circuits that are able to be run on the hardware.  `Device` objects specify these constraints and can be used to validate your circuit to make sure that it contains no illegal operations. For more information on what constraints `Device` objects can specify and how to use them, see the [Devices](../hardware/devices.ipynb) page.\n",
    "\n",
    "The following example demonstrates this with the Sycamore Device:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "9UV-dXJOpy8B"
   },
   "outputs": [],
   "source": [
    "# Create some qubits.\n",
    "q0 = cirq.GridQubit(5, 6)\n",
    "q1 = cirq.GridQubit(5, 5)\n",
    "q2 = cirq.GridQubit(4, 5)\n",
    "\n",
    "# Create operations using the Sycamore gate, which is supported by the Sycamore device.\n",
    "# However, create operations for both adjacent and non-adjacent qubit pairs.\n",
    "adjacent_op = cirq_google.SYC(q0, q1)\n",
    "nonadjacent_op = cirq_google.SYC(q0, q2)\n",
    "\n",
    "# A working circuit for the Sycamore device raises no issues.\n",
    "working_circuit = cirq.Circuit()\n",
    "working_circuit.append(adjacent_op)\n",
    "valid = cirq_google.Sycamore.validate_circuit(working_circuit)\n",
    "\n",
    "# A circuit using invalid operations.\n",
    "bad_circuit = cirq.Circuit()\n",
    "bad_circuit.append(nonadjacent_op)\n",
    "try:\n",
    "    cirq_google.Sycamore.validate_circuit(bad_circuit)\n",
    "except ValueError as e:\n",
    "    print(e)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "xZ68bWEjoMKt"
   },
   "source": [
    "## Simulation\n",
    "\n",
    "The results of the application of a quantum circuit can be calculated by a `Simulator`.  Cirq comes bundled with a simulator that can calculate the results of circuits up to about a limit of 20 qubits.  It can be initialized with `cirq.Simulator()`.\n",
    "\n",
    "There are two different approaches to using a simulator:\n",
    "\n",
    "*   `simulate()`:  When classically simulating a circuit, a simulator can directly access and view the resulting wave function.  This is useful for debugging, learning, and understanding how circuits will function.  \n",
    "*   `run()`:  When using actual quantum devices, we can only access the end result of a computation and must sample the results to get a distribution of results.  Running the simulator as a sampler mimics this behavior and only returns bit strings as output.\n",
    "\n",
    "Next simulate a 2-qubit \"Bell State\":"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "AwC4SL6CHpXm"
   },
   "outputs": [],
   "source": [
    "# Create a circuit to generate a Bell State:\n",
    "# 1/sqrt(2) * ( |00⟩ + |11⟩ )\n",
    "bell_circuit = cirq.Circuit()\n",
    "q0, q1 = cirq.LineQubit.range(2)\n",
    "bell_circuit.append(cirq.H(q0))\n",
    "bell_circuit.append(cirq.CNOT(q0, q1))\n",
    "\n",
    "# Initialize Simulator\n",
    "s = cirq.Simulator()\n",
    "\n",
    "print('Simulate the circuit:')\n",
    "results = s.simulate(bell_circuit)\n",
    "print(results)\n",
    "\n",
    "# For sampling, we need to add a measurement at the end\n",
    "bell_circuit.append(cirq.measure(q0, q1, key='result'))\n",
    "\n",
    "# Sample the circuit\n",
    "samples = s.run(bell_circuit, repetitions=1000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "a9a791442b74"
   },
   "source": [
    "### Virtual Machine Simulation\n",
    "\n",
    "Cirq also provides the [Quantum Virtual Machine](../simulate/quantum_virtual_machine.ipynb), which is a simulated virtual version of quantum hardware devices. It consists of two primary components: \n",
    "1. A [virtual Engine interface](../simulate/virtual_engine_interface.ipynb) that enables you to verify and run circuits with the same interface that quantum hardware would have.\n",
    "2. A set of [noise models](../noise/representing_noise.ipynb) that try to realistically replicate the noise present in actual Google quantum hardware devices.\n",
    "\n",
    "The QVM is intended to serve as a replacement for the Google quantum hardware, in two cases: \n",
    "1. Running your circuit on a QVM can give an approximation of how your circuit runs under the influence of hardware-like noise. This can be useful to help you reconfigure or change your circuit to be less impacted by noise when run on actual quantum hardware.\n",
    "2. During the preparation process before running your circuit(s) on hardware, you can seamlessly use a QVM to test that your workflow or pipeline works before eventually switching to the nearly-identical hardware interface.\n",
    "\n",
    "Read more about the QVM and its uses in the [Quantum Virtual Machine](../simulate/quantum_virtual_machine.ipynb) page, or just start using it with the [QVM Creation Template](../simulate/qvm_builder_code.ipynb) page."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "be79fa541b8a"
   },
   "source": [
    "## Visualizing Results\n",
    "\n",
    "When you use `run()` to get a sample distribution of measurements, you can directly graph the simulated samples as a histogram with `cirq.plot_state_histogram`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "69dca44091f4"
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "cirq.plot_state_histogram(samples, plt.subplot())\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "b4f20cffe4ae"
   },
   "source": [
    "However, this histogram has some empty qubit states, which may become problematic if you work with more qubits. To graph sparse sampled data, first get the `Counts` from your results with its `histogram()` function, and pass that to `cirq.plot_state_histogram`. By collecting the results into counts, all the qubit states that were never seen are ignored."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "07ec16b02594"
   },
   "outputs": [],
   "source": [
    "# Pull of histogram counts from the result data structure\n",
    "counts = samples.histogram(key='result')\n",
    "print(counts)\n",
    "\n",
    "# Graph the histogram counts instead of the results\n",
    "cirq.plot_state_histogram(counts, plt.subplot())\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ef90dabdd52e"
   },
   "source": [
    "A histogram over the states that were actually observed can often be more useful when analyzing results. To learn more about the available options for creating result histograms, see the [State Histograms](../simulate/state_histograms.ipynb) page. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "06Q_7vlQSu4Z"
   },
   "source": [
    "### Using parameter sweeps\n",
    "\n",
    "Cirq circuits allow for gates to have symbols as free parameters within the circuit.  This is especially useful for variational algorithms, which vary parameters within the circuit in order to optimize a cost function, but it can be useful in a variety of circumstances.\n",
    "\n",
    "For parameters, Cirq uses the library `sympy` to add `sympy.Symbol` as parameters to gates and operations.  \n",
    "\n",
    "Once the circuit is complete, you can fill in the possible values of each of these parameters with a `Sweep`.  There are several possibilities that can be used as a sweep:\n",
    "\n",
    "*   `cirq.Points`: A list of manually specified values for one specific symbol as a sequence of floats.\n",
    "*   `cirq.Linspace`: A linear sweep from a starting value to an ending value.\n",
    "*   `cirq.ListSweep`: A list of manually specified values for several different symbols, specified as a list of dictionaries.\n",
    "*   `cirq.Zip` and `cirq.Product`: Sweeps can be combined list-wise by zipping them together or through their Cartesian product.\n",
    "\n",
    "A parameterized circuit and sweep together can be run using the simulator or other sampler by changing `run()` to `run_sweep()` and adding the sweep as a parameter.\n",
    "\n",
    "Here is an example of sweeping an exponent of a X gate:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "ElyizofbLGq9"
   },
   "outputs": [],
   "source": [
    "import sympy\n",
    "\n",
    "# Perform an X gate with variable exponent\n",
    "q = cirq.GridQubit(1, 1)\n",
    "circuit = cirq.Circuit(cirq.X(q) ** sympy.Symbol('t'), cirq.measure(q, key='m'))\n",
    "\n",
    "# Sweep exponent from zero (off) to one (on) and back to two (off)\n",
    "param_sweep = cirq.Linspace('t', start=0, stop=2, length=200)\n",
    "\n",
    "# Simulate the sweep\n",
    "s = cirq.Simulator()\n",
    "trials = s.run_sweep(circuit, param_sweep, repetitions=1000)\n",
    "\n",
    "# Plot all the results\n",
    "x_data = [trial.params['t'] for trial in trials]\n",
    "y_data = [trial.histogram(key='m')[1] / 1000.0 for trial in trials]\n",
    "plt.scatter('t', 'p', data={'t': x_data, 'p': y_data})\n",
    "plt.xlabel(\"trials\")\n",
    "plt.ylabel(\"frequency of qubit measured to be one\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "M8oLYwusz4XE"
   },
   "source": [
    "## Unitary matrices and decompositions\n",
    "\n",
    "Many quantum operations have unitary matrix representations.  This matrix can be accessed by applying `cirq.unitary(operation)` to that `operation`.  This can be applied to gates, operations, and circuits that support this protocol and will return the unitary matrix that represents the object. See [Protocols](../build/protocols.ipynb) for more about this and other protocols."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "xn9nnBA70s23"
   },
   "outputs": [],
   "source": [
    "print('Unitary of the X gate')\n",
    "print(cirq.unitary(cirq.X))\n",
    "\n",
    "print('Unitary of SWAP operator on two qubits.')\n",
    "q0, q1 = cirq.LineQubit.range(2)\n",
    "print(cirq.unitary(cirq.SWAP(q0, q1)))\n",
    "\n",
    "print('Unitary of a sample circuit')\n",
    "print(cirq.unitary(cirq.Circuit(cirq.X(q0), cirq.SWAP(q0, q1))))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Ls6Tnx90Y94Q"
   },
   "source": [
    "### Decompositions \n",
    "\n",
    "Many gates can be decomposed into an equivalent circuit with simpler operations and gates.  This is called decomposition and can be accomplished with the `cirq.decompose` protocol.  \n",
    "\n",
    "For instance, a Hadamard H gate can be decomposed into X and Y gates:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "u8JwZaAUfbSv"
   },
   "outputs": [],
   "source": [
    "print(cirq.decompose(cirq.H(cirq.LineQubit(0))))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "B8ciZZSSf2jb"
   },
   "source": [
    "Another example is the 3-qubit Toffoli gate, which is equivalent to a controlled-controlled-X gate.  Many devices do not support three qubit gates, so it is important to decompose them into one and two qubit gates."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "bbjRWlzjgPwf"
   },
   "outputs": [],
   "source": [
    "q0, q1, q2 = cirq.LineQubit.range(3)\n",
    "print(cirq.Circuit(cirq.decompose(cirq.TOFFOLI(q0, q1, q2))))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "VWcik4ZwggXj"
   },
   "source": [
    "The above decomposes the Toffoli into a simpler set of one-qubit gates and two-qubit CZ gates at the cost of lengthening the circuit considerably."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "rIUbvdVQkHbX"
   },
   "source": [
    "### Transformers\n",
    "\n",
    "The last concept in this tutorial is the transformer.  A transformer can take a circuit and modify it.  Usually, this will entail combining or modifying operations to make it more efficient and shorter, though a transformer can, in theory, do any sort of circuit manipulation.\n",
    "\n",
    "For example, the `cirq.merge_single_qubit_gates_to_phxz` transformer will take consecutive single-qubit operations and merge them into a single `PhasedXZ` operation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "5WvfOdaG5C_6"
   },
   "outputs": [],
   "source": [
    "q = cirq.GridQubit(1, 1)\n",
    "c = cirq.Circuit(cirq.X(q) ** 0.25, cirq.Y(q) ** 0.25, cirq.Z(q) ** 0.25)\n",
    "print(c)\n",
    "c = cirq.merge_single_qubit_gates_to_phxz(c)\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "xRfQqzdx7lUI"
   },
   "source": [
    "Other transformers can assist in transforming a circuit into operations that are native operations on specific hardware devices.  You can find more about transformers and how to create your own in [Transformers](../transform/transformers.ipynb)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "8QbTGmKlYT4i"
   },
   "source": [
    "## Next steps\n",
    "\n",
    "After completing this tutorial, you should be able to use gates and operations to construct your own quantum circuits, to simulate them, and to use sweeps.\n",
    "\n",
    "There is much more to learn and try out for those who are interested:\n",
    "\n",
    "* Learn about the variety of [Gates](../build/gates.ipynb) available in Cirq and more about the different ways to construct [Circuits](../build/circuits.ipynb).\n",
    "* Learn more about [Simulations](../simulate/simulation.ipynb) and how it works.\n",
    "* Learn about [Noise](../noise) and how to utilize multi-level systems using [Qudits](../build/qudits.ipynb).\n",
    "* Dive into some [Experiments](../experiments) and some in-depth tutorials of how to use cirq.\n",
    "\n",
    "Also, join our [cirq-announce mailing list](https://groups.google.com/forum/#!forum/cirq-announce) to hear about changes and releases or go to the [Cirq GitHub repository](https://github.com/quantumlib/Cirq/) to file issues."
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "basics.ipynb",
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
